package com.lifesting.front;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.FacesEvent;
import javax.faces.event.FacesListener;

import com.lifesting.HbUtil;

/**
 * 表格控件
 * 
 * @author david
 * 
 */
public class Table extends UIComponentBase implements NamingContainer {

	public static class RnsListener implements FacesListener {

	}

	public static class FilterListener implements FacesListener {

	}

	public static class SorterListener implements FacesListener {

	}

	public static class PageChangeListener implements FacesListener {

	}

	public static class DeleteListener implements FacesListener {

	}

	public static final String COMPONENT_TYPE = "com.lifesting.table";
	public static final String COMPONENT_FAMILY = "com.lifesting.family";
	// 行是否可以选择，如果选择的话，将会在第一列显示一个checkbox
	private Boolean rowsCheckable;
	// hibernate bean名称，将会以这个从hibernate中查询数据
	private String beanName;
	// 行数，于RowsNumberSetting结合，这里有个默认值
	private Integer rowsCount = 20;
	// 数据模型，需要么？
	// ignore data model
	// 变量，给每行使用的
	private String var;
	// 总记录数，通过计算得出
	private Integer totalCount = 0;
	// 总页数，通过计算得出
	private Integer totalPages = 1;
	// 当前页记录数
	private List<Record> records;
	// 唯一标识表格的列
	private String idField;
	// 要过滤的field
	private String filterField;
	// 过滤条件
	private String filterLike;

	public String getFilterField() {
		return filterField;
	}

	public void setFilterField(String filterField) {
		this.filterField = filterField;
	}

	public String getFilterLike() {
		return filterLike;
	}

	public void setFilterLike(String filterLike) {
		this.filterLike = filterLike;
	}

	public String getIdField() {
		return idField;
	}

	public void setIdField(String idField) {
		this.idField = idField;
	}

	public Integer getTotalCount() {
		return totalCount;
	}

	public Integer getTotalPages() {
		return totalPages;
	}

	public Table() {

	}

	public void paginate() {
		calculatePages();
		try {
			aclulateRecords();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 只关注过滤条件，其他可忽略
	private void calculatePages() {
		totalCount = HbUtil.getTotalCount(beanName, filterField, filterLike);
		if (totalCount < 1) {
			// 错误或真的没有一条数据
			totalPages = 1;
		} else {
			int tmp_pages = (int) Math.ceil(totalCount * 1.0 / rowsCount * 1.0);
			totalPages = Integer.valueOf(tmp_pages);
		}
		if (currentPage > totalPages)
			currentPage = totalPages;
		if (currentPage < 1)
			currentPage = 1;
	}

	private Integer currentPage = 1;

	public Boolean getRowsCheckable() {
		return rowsCheckable;
	}

	public void setRowsCheckable(Boolean rowsCheckable) {
		this.rowsCheckable = rowsCheckable;
	}

	public String getBeanName() {
		return beanName;
	}

	public void setBeanName(String beanName) {
		this.beanName = beanName;
	}

	public Integer getRowsCount() {
		return rowsCount;
	}

	public void setRowsCount(Integer rowsCount) {
		this.rowsCount = rowsCount;
	}

	public String getVar() {
		return var;
	}

	public void setVar(String var) {
		this.var = var;
	}

	public Integer getCurrentPage() {
		return currentPage;
	}

	public void setCurrentPage(Integer currentPage) {
		this.currentPage = currentPage;
	}

	// 每次设置完页码后，
	private void aclulateRecords() throws Exception {
		if (records != null)
			records.clear();
		records = new ArrayList<Record>(rowsCount);
		Method method = null;
//		boolean need_convert = false;
		Class beanClass = Class.forName(FacesUtil.getQualifiedName(beanName));
		List pageData = HbUtil.getRowsData(this);
		for (Iterator ite = pageData.iterator(); ite.hasNext();) {
			Object row_data = ite.next();
			Record rec = new Record();
			if (method == null) {
				// 只做个简单的命名规则，将首字母大写
				char[] chars = idField.toCharArray();
				if (0x5A < chars[0]) {// 转换为大写
					chars[0] -= 0x20;
				}
				String method_name = "get" + String.valueOf(chars);
				method = beanClass.getDeclaredMethod(method_name);
//				Field field = beanClass.getDeclaredField(idField);
//				need_convert = field.getType() != Long.class;
			}
			Object unique_id = method.invoke(row_data);
			rec.setUniqueId(String.valueOf(unique_id));
			/*if (need_convert) {
				rec.setUniqueId(Long.valueOf(String.valueOf(unique_id)));
			} else {
				rec.setUniqueId((Long) unique_id);
			}*/
			rec.setWrapped(row_data);
			records.add(rec);
		}
	}

	public Integer getTotalRowsCount() {
		return totalRowsCount;
	}

	// 行总数，每次计算，不用saveState
	private Integer totalRowsCount;

	@Override
	public String getFamily() {
		return COMPONENT_FAMILY;
	}

	private Object[] values;

	@Override
	public Object saveState(FacesContext context) {
		if (null == values) {
			values = new Object[10];
		}
		values[0] = super.saveState(context);
		values[1] = rowsCheckable;
		values[2] = beanName;
		values[3] = rowsCount;
		values[4] = var;
		values[5] = currentPage;
		values[6] = totalPages;
		values[7] = idField;
		values[8] = filterField;
		values[9] = filterLike;
		return values;
	}

	public Record getRowRecord(int rowIndex) {
		return records.get(rowIndex);
	}

	public int getReallyPageCount() {
		return records.size();
	}

	@Override
	public void restoreState(FacesContext context, Object state) {
		values = (Object[]) state;
		super.restoreState(context, values[0]);
		rowsCheckable = (Boolean) values[1];
		beanName = (String) values[2];
		rowsCount = (Integer) values[3];
		var = (String) values[4];
		setCurrentPage((Integer) values[5]);
		totalPages = (Integer) values[6];
		idField = (String) values[7];
		filterField = (String) values[8];
		filterLike = (String) values[9];
	}

	@Override
	public void broadcast(FacesEvent event) throws AbortProcessingException {
		super.broadcast(event);
		if (event instanceof RnsEvent) {
			setRowsCount(((RnsEvent) event).getNumber());
			setCurrentPage(1);
		} else if (event instanceof FilterEvent) {
			setFilterField(((FilterEvent) event).getFilterField());
			setFilterLike(((FilterEvent) event).getFilterLike());
		} else if (event instanceof PageChangeEvent) {
			setCurrentPage(((PageChangeEvent) event).getPageNumber());
		} else if (event instanceof DeleteEvent) {
			deleteRows(getFacesContext(), ((DeleteEvent) event).getIds());
		}
	}

	private void deleteRows(FacesContext context, String[] ids) {
		int deleted = HbUtil.deleteRows(context, this, ids);
		if (deleted > 0) {
			FacesMessage msg = new FacesMessage();
			msg.setSeverity(FacesMessage.SEVERITY_INFO);
			msg.setSummary("刪除了 " + deleted + " 条记录!");
			context.addMessage(getClientId(context), msg);
		}
	}
}
